#coding=utf-8
#LightCam 代理服务程序
#init by hfh 20150212

import socket,os,time,re,subprocess,multiprocessing,traceback,lc_libs,sys
import SocketServer

#class LCSocketServer(SocketServer.ThreadingTCPServer):
#	def __init__(self,ADDR,LCAgent):
#		SocketServer.ThreadingTCPServer.__init__(self,ADDR,LCAgent)
		
	#def InitArgvs(self,agent_hostname,AgentList):
	#	self.BUFSIZ=8192
	#	self.s={}
	#	self.agent_hostname=agent_hostname
	#	self.AgentList=AgentList
	#	print self.agent_hostname
	#	print self.AgentList
		

class LCAgent(SocketServer.StreamRequestHandler):
	
	#def __init__(self,agent_hostname,AgentList):
	#def __init__(self):
		
		#self.BUFSIZ=8192
		#self.s={}
		
		#print self.BUFSIZ
		#print self.agents
		#self.agent_hostname=agent_hostname
		#self.AgentList=AgentList
		#rint self.agent_hostname
		#print self.AgentList
		
		#self.InitAgentList()

	#def InitArgvs(self):
	#	self.agents={}

	def GenAgentPath(self,agentname):
		if agentname in AgentList.keys():
			flag=1
			tempname=agentname
			while flag:
				time.sleep(0.01)
				if tempname==agent_hostname:
					return tempname
				if AgentList[tempname]['fathername']=='self':
					return tempname
				elif AgentList[tempname]['fathername']==agent_hostname:
					return tempname
				else:
					tempname=AgentList[tempname]['fathername']
					#print "tempname:"+tempname
		else:
			return "NoSuchAgent"
			
	def InitAgentList(self):
		for key,value in AgentList.items():
			if value['fathername']==agent_hostname:
				ADDR=(value['agentip'],value['agentport'])
				logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
				print "%s %s trying connect to [%s] , IP:[%s] Port:[%s]" % (logdate,agent_hostname,key,value['agentip'],value['agentport'])
				if agents.has_key(key):
					agents[key].close()
				agents[key] = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
				try:
					agents[key].connect(ADDR)
					agents[key].sendall("__ESTABLISHED__")
					time.sleep(1)
					res=agents[key].recv(BUFSIZ)
					if re.match("__ESTABLISHED__",res):
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print "%s %s Connected to [%s]" % (logdate,agent_hostname,key)
						#print dir(agents[key])
						pass
					else:
						print "%s %s can't connect to [%s]" % (logdate,agent_hostname,key)
				except Exception:
					excinfo=traceback.format_exc()
					print excinfo
				
				#print agents[key].getpeername()
				#('172.31.112.247', 8640)
				
				#print agents[key].getsockname()
				#('172.31.112.246', 20689)
				
				#print agents[key].gettimeout()
				#default:None
				#agents[key].settimeout(300)
				

	def OperEstablishedCommand(self):
		print "[Debug]SelfRequest:%s" % self.request
		self.request.sendall('__ReadyForEstablishedCommand__')
		sd=''
		while True:
			time.sleep(0.01)
			buf=self.request.recv(BUFSIZ)
			print "[Debug]OperEstablishedCommand:%s" % buf
			sd=sd+buf
			if re.match(".*__EndOfEstablishedCommand__",sd):
				rest=sd.replace("__EndOfEstablishedCommand__","").split('__')
				if len(rest)<2:
					self.request.sendall('IllegalCommand__EndOfTheResult__')
					break
				agentname=rest[0]
				comd=rest[1]
				logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
				print "%s %s Agent:[%s] Command:[%s]" % (logdate,agent_hostname,agentname,comd)
				nextagent=self.GenAgentPath(agentname)
				print "%s %s NextAgent:[%s]" % (logdate,agent_hostname,agentname)
				if nextagent=='NoSuchAgent':
					self.request.sendall('NoSuchAgent__EndOfTheResult__')
				elif nextagent==agent_hostname:
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print "%s %s Command:[%s]" % (logdate,agent_hostname,comd)
					if comd=='InitAgentList':
						self.InitAgentList()
						print "%s %s Result:[InitAgentList]" % (logdate,agent_hostname)
						self.request.sendall('InitAgentList__EndOfTheResult__')
						break
					elif comd=='HeartBeat':
						print "%s %s Result:[HeartBeat]" % (logdate,agent_hostname)
						self.request.sendall(agent_hostname+' HeartBeat OK__EndOfTheResult__')
						break
					else:
						popen=subprocess.Popen(comd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
						line=popen.stdout.read().strip('\n\r ')
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print "%s %s Result:[%s]" % (logdate,agent_hostname,line)
						self.request.sendall(line+"__EndOfTheResult__")
						break
				else:
					if agents.has_key(nextagent):
						agents[nextagent].sendall("__StartOfEstablishedCommand__")
						sd=''
						while True:
							time.sleep(0.01)
							res=agents[nextagent].recv(BUFSIZ)
							print "[Debug]__StartOfEstablishedCommand__ for next agent:%s" % res
							if re.findall("__ReadyForEstablishedCommand__",res):
								agents[nextagent].sendall(agentname+"__"+comd+"__EndOfEstablishedCommand__")
								continue
							sd=sd+res
							res=re.findall(r"__EndOfTheResult__",sd,re.S)
							if len(res) <> 0:
								sd=sd.replace("__EndOfTheResult__","").strip('\n\r ').strip('[]')
								logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
								print "%s %s Result:[%s]" % (logdate,agent_hostname,sd)
								self.request.sendall(sd+"__EndOfTheResult__")
								break
						break
					else:
						self.request.sendall('AgentNotInit__EndOfTheResult__')

	def OperEstablishedPutFile(self,recv_data):
		rest=recv_data.replace("__StartOfEstablishedPutFile__","").split('__')
		if len(rest)<3:
			#self.request.sendall('IllegalCommand__EndOfTheResult__')
			return 'IllegalFile'
		agentname=rest[0]
		filesize=int(rest[1])
		remotefile=rest[2]
		
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		print "%s %s Agent:[%s] RemoteFile:[%s] FileSize:[%s]" % (logdate,agent_hostname,agentname,remotefile,filesize)
		nextagent=self.GenAgentPath(agentname)
		if nextagent=='NoSuchAgent':
			self.request.sendall('NoSuchAgent__EndOfTheResult__')
			return 'NoSuchAgent'
		else:
			print "%s %s NextAgent:[%s]" % (logdate,agent_hostname,agentname)
		
		recv_data=''
		rfilesize=filesize
		self.request.sendall('__ReadyForEstablishedPutFile__')
		
		if nextagent==agent_hostname:
			fileoper = open(remotefile,'wb')
			while True:
				time.sleep(0.001)
				recv_datas=''
				if rfilesize>BUFSIZ:
					recv_datas = self.request.recv(BUFSIZ)
				else:
					recv_datas = self.request.recv(rfilesize)
				fileoper.write(recv_datas)
				rfilesize=rfilesize-len(recv_datas)
				pert=round(100.0-100.0*rfilesize/filesize,2)
				print "\r"+str(pert)+"%",
				if rfilesize<=0:
					break
			fileoper.flush()
			fileoper.close()
			#self.request.sendall('__EndForEstablishedPutFile__')
			logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
			print "\n%s %s 文件接收成功,已保存到[%s]" % (logdate,agent_hostname,remotefile)
		else:
			msg="%s__%s__%s__StartOfEstablishedPutFile__" % (agentname,filesize,remotefile)
			agents[nextagent].sendall(msg)
			res=agents[nextagent].recv(BUFSIZ)
			if re.findall("__ReadyForEstablishedPutFile__",res):
				while True:
					time.sleep(0.001)
					recv_datas=''
					if rfilesize>BUFSIZ:
						recv_datas = self.request.recv(BUFSIZ)
					else:
						recv_datas = self.request.recv(rfilesize)
					agents[nextagent].sendall(recv_datas)
					rfilesize=rfilesize-len(recv_datas)
					pert=round(100.0-100.0*rfilesize/filesize,2)
					print "\r"+str(pert)+"%",
					if rfilesize<=0:
						break
				#while True:
				#	time.sleep(0.01)
				#	sd=agents[nextagent].recv(BUFSIZ)
				#	#print "[Debug]%s" % sd
				#	if re.findall("__EndForEstablishedPutFile__",sd):
				#		break
				#self.request.sendall('__EndForEstablishedPutFile__')

	def OperEstablishedGetFile(self,recv_data):
		rest=recv_data.replace("__StartOfEstablishedGetFile__","").split('__')
		if len(rest)<3:
			#self.request.sendall('IllegalCommand__EndOfTheResult__')
			return 'IllegalFile'
		agentname=rest[0]
		localfile=rest[1]
		remotefile=rest[2]
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		print "%s %s Agent:[%s] RemoteFile:[%s]" % (logdate,agent_hostname,agentname,remotefile)
		nextagent=self.GenAgentPath(agentname)
		if nextagent=='NoSuchAgent':
			self.request.sendall('NoSuchAgent__EndOfTheResult__')
			return 'NoSuchAgent'
		else:
			print "%s %s NextAgent:[%s]" % (logdate,agent_hostname,agentname)
		
		#self.request.sendall('__ReadyForEstablishedGetFile__')
		if nextagent==agent_hostname:
			if os.path.exists(remotefile):
				logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
				print "%s %s 准备发送文件:[%s]" % (logdate,agent_hostname,remotefile)
			else:
				logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
				print "%s %s 文件[%s]不存在" % (logdate,agent_hostname,remotefile)
				self.request.sendall("__FileNotExist__")
				return 'NoSuchFile'

			fileoper=open(remotefile,'rb')
			filesize=os.path.getsize(remotefile)
			
			logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
			print "%s %s 文件大小为:[%s]" % (logdate,agent_hostname,filesize)
			self.request.sendall("__BUFSIZS__"+str(filesize)+"__BUFSIZE__")
			
			while True:
				time.sleep(0.01)
				res=self.request.recv(BUFSIZ)
				if re.match("__ReadyForEstablishedGetFile__",res):
					rfilesize=filesize
					#self.request.sendall("__StartOfFile__")
					while True:
						time.sleep(0.001)
						send_datas=''
						if rfilesize>BUFSIZ:
							send_datas = fileoper.read(BUFSIZ)
						else:
							send_datas = fileoper.read(rfilesize)
						self.request.sendall(send_datas)
						rfilesize=rfilesize-len(send_datas)
						pert=round(100.0-100.0*rfilesize/filesize,2)
						print "\r "+str(pert)+"%",
						if rfilesize<=0:
							break
					#self.request.sendall("__EndOfFile__")
					fileoper.close()
					#break
					#self.request.sendall('__EndForEstablishedPutFile__')
				#if re.match("__EndForEstablishedGetFile__",res):
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print "\n%s %s 文件[%s]发送成功" % (logdate,agent_hostname,localfile)
					break
		else:
			msg="__StartOfEstablishedGetFile__%s__%s__%s__" % (agentname,localfile,remotefile)
			agents[nextagent].sendall(msg)
			while True:
				time.sleep(0.01)
				recv_data=''
				try:
					res=agents[nextagent].recv(BUFSIZ)
				except:
					pass
				if re.match("__FileNotExist__",res):
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print "%s %s ,文件[%s]读取失败" % (logdate,agent_hostname,remotefile)
					self.request.sendall('__FileNotExist__')
					break
				elif re.match("__BUFSIZS__",res):
					filesize=re.findall(r"__BUFSIZS__(.*)__BUFSIZE__",res,re.S)
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print "%s %s ,准备下载文件[%s],文件大小为[%s]" % (logdate,agent_hostname,remotefile,filesize[0])
					if len(filesize)==0:
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print "%s %s ,文件[%s]为空" % (logdate,agent_hostname,remotefile,filesize[0])
						self.request.sendall('__FileNoContent__')
						break
					else:
						self.request.sendall("__BUFSIZS__"+str(filesize[0])+"__BUFSIZE__")
						filesize=int(filesize[0])
						agents[nextagent].sendall("__ReadyForEstablishedGetFile__")
						recv_data=''
						rfilesize=filesize
						while True:
							time.sleep(0.001)
							recv_datas=''
							if rfilesize>BUFSIZ:
								recv_datas = agents[nextagent].recv(BUFSIZ)
							else:
								recv_datas = agents[nextagent].recv(filesize)
							self.request.sendall(recv_datas)
							rfilesize=rfilesize-len(recv_datas)
							pert=round(100.0-100.0*rfilesize/filesize,2)
							print "\r "+str(pert)+"%",
							if rfilesize<=0:
								time.sleep(0.001)
								break
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print "%s %s ,文件[%s]传输成功" % (logdate,agent_hostname,remotefile)
						#agents[nextagent].sendall('__EndForEstablishedGetFile__')
						#self.request.sendall('__EndForEstablishedGetFile__')
						break
						
	def handle(self):
		try:
			
			global BUFSIZ
			global agents
			
			while True:
				time.sleep(0.01)
				
				recv_data=''
				try:
					recv_data = self.request.recv(BUFSIZ)
				except Exception:
					excinfo=traceback.format_exc()
					print excinfo
					pass
				
				thistime=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
				print "%s %s DataReceived" % (thistime,agent_hostname)
				#print "%s %s DataReceived: %s" % (thistime,agent_hostname,recv_data)
				
				if len(recv_data)==0:
					time.sleep(0.01)
					break
				
				elif re.findall("__StartOfTheCommand__",recv_data):
					self.request.sendall('__ReadyForTheCommand__')
					sd=''
					while True:
						buf=self.request.recv(BUFSIZ)
						sd=sd+buf
						if re.match(".*__EndOfTheCommand__",sd):
							comd=sd.replace("__EndOfTheCommand__","")
							logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
							print logdate+" Command: "+str(comd)
							#logfile.write(logdate+" CMD:"+str(cmd)+"\n")
							popen=subprocess.Popen(comd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
							while True:
								if popen.poll()==None:
									time.sleep(0.01)
									continue
								else:
									break
							line=popen.stdout.read()
							logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
							print logdate+" Result: "+line
							#logfile.write(logdate+" "+line+"\n")
							self.request.sendall(line+"__EndOfTheResult__")
							break
						time.sleep(0.01)
					time.sleep(0.01)
					break
					
				elif re.findall("__StartOfPutFile__",recv_data):
					filesize=re.findall(r"__BUFSIZS__(.*)__BUFSIZE__",recv_data,re.S)
					if len(filesize)==0:
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print logdate+",文件大小为空"
						break
					filesize=int(filesize[0])
					filename=re.findall(r"__FILENAMES__(.*)__FILENAMEE__",recv_data,re.S)
					if len(filename)==0:
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print logdate+",文件名称为空"
						break
					filename=filename[0]
					self.request.sendall('__ReadyForPutFile__')
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print logdate+",准备接收文件"+filename
					sd=''
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print logdate+",文件大小为"+str(filesize)
					recv_data=''
					rfilesize=filesize
					fileoper = open(filename,'wb')
					while True:
						recv_datas=''
						if rfilesize>BUFSIZ:
							recv_datas = self.request.recv(BUFSIZ)
						else:
							recv_datas = self.request.recv(filesize)
						fileoper.write(recv_datas)
						rfilesize=rfilesize-len(recv_datas)
						pert=100-100*rfilesize/filesize
						print "\r"+str(pert)+"%",
						#sys.stdout.write("\r"+str(pert)+"%",)
						#sys.stdout.flush()
						if rfilesize==0:
							break
					fileoper.flush()
					fileoper.close()
					self.request.sendall('__EndForPutFile__')
					self.request.close()
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print logdate+",文件接收成功,已保存到"+filename
					break
					
				elif re.findall("__StartOfGetFile__",recv_data):
					filename=re.findall(r"__FILENAMES__(.*)__FILENAMEE__",recv_data,re.S)
					filename=filename[0]
					if os.path.isfile(filename):
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print logdate+',准备发送文件'+filename
					else:
						logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
						print logdate+',文件'+filename+'不存在'
						self.request.sendall("__FileNotExist__")
						self.request.close()
						break
					
					fileoper=open(filename,'rb')
					filedata=fileoper.read()
					filelength=len(filedata)
					fileoper.close()
					
					logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
					print logdate+',文件大小为'+str(filelength)
					
					self.request.sendall("__BUFSIZS__"+str(filelength)+"__BUFSIZE__")

					while True:
						res=self.request.recv(BUFSIZ)
						if re.match("__ReadyForGetFile__",res):
							self.request.sendall(filedata)
						if re.match("__EndForGetFile__",res):
							logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
							print logdate+',文件'+filename+'发送成功'
							self.request.close()
							break
						time.sleep(0.01)
					time.sleep(0.01)
					break
				
				elif re.findall("__ESTABLISHED__",recv_data):
					self.request.sendall('__ESTABLISHED__')
					while True:
						time.sleep(0.01)
						recv_data = self.request.recv(BUFSIZ)
						if re.findall("__StartOfEstablishedCommand__",recv_data):
							self.OperEstablishedCommand()
							#print "COMD OK"
						elif re.findall("__StartOfEstablishedPutFile__",recv_data):
							self.OperEstablishedPutFile(recv_data)
							#print "Put OK"
						elif re.findall("__StartOfEstablishedGetFile__",recv_data):
							self.OperEstablishedGetFile(recv_data)
							#print "GET OK"

				#elif re.match("__InitArgvs__",recv_data):
				#	print "Command Recevied: init argvs"
				#	self.InitArgvs()
				#	self.request.sendall('__InitArgvs__')
				#
				#elif re.match("__InitAgentList__",recv_data):
				#	print "Command Recevied: init agent list "
				#	self.InitAgentList()
				#	self.request.sendall('__InitAgentList__')

				elif re.findall("__StartOfEstablishedCommand__",recv_data):
					self.OperEstablishedCommand()

				elif re.findall("__StartOfEstablishedPutFile__",recv_data):
					self.OperEstablishedPutFile(recv_data)
					
				elif re.findall("__StartOfEstablishedGetFile__",recv_data):
					self.OperEstablishedGetFile(recv_data)
					
				#elif re.match("__StopAgent__",recv_data):
				#	self.request.sendall('__ReadyToStopAgent__')
				#	for name in agents.keys():
				#		agents[name].close()
				#	server.shutdown()
					
		except Exception:
			excinfo=traceback.format_exc()
			print excinfo
			pass
 
if __name__ == '__main__':

	agent_hostname=lc_libs.lc_gethostname()
	
	#初始化
	lchome=lc_libs.lc_getlchome()
	scname=sys.argv[0].split('.')[0]
	logfilename=lchome+'/log/'+scname+'.log'
	confname=lchome+'/conf/'+scname+'.conf'
	
	today=time.strftime('%Y%m%d',time.localtime())
	os.system("mv %s %s.%s" % (logfilename,logfilename,today))
	
	logfile=file(logfilename,'a')
	logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
	logfile.write(logdate+" Started.\n")
	logfile.flush()
	
	ADDR=("0.0.0.0",1960)
	AgentList={}

	BUFSIZ=8192
	agents={}
	
	#程序处理
	try:
		for line in open(confname):
			if line[0] == '#':
				continue
			else:
				lines=line.strip('\n').split("\t")
				if len(lines)<3:
					continue
				else:
					AgentList[lines[0]]={
						'agentip':lines[1],
						'agentport':int(lines[2]),
						'fathername':lines[3],
						'fatherip':lines[4],
						'fatherport':int(lines[5])
					}
					if lines[0]==agent_hostname:
						#ADDR=(str(lines[1],int(lines[2]))
						ADDR=("0.0.0.0",int(lines[2]))
		#server = SocketServer.ThreadingTCPServer(ADDR,LCAgent(agent_hostname,AgentList))
		server = SocketServer.ThreadingTCPServer(ADDR,LCAgent)
		#server=LCSocketServer(ADDR,LCAgent(agent_hostname,AgentList))
		#print dir(server)
		#server.InitArgvs(agent_hostname,AgentList)
		#server.InitAgentList()
		server.serve_forever()
	
	except Exception:
		#server.shutdown()
		excinfo=traceback.format_exc()
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		logfile.write(logdate+" "+excinfo+"\n")
		logfile.flush()
		exit()
